package cn.edu.sjtu.se.dslab.rhapsody.parse;

import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.stereotype.Service;

import cn.edu.sjtu.se.dslab.component.data.DomainEntity;
import cn.edu.sjtu.se.dslab.service.IDataTypeService;
import cn.edu.sjtu.se.dslab.service.IDomainEntityService;
import cn.edu.sjtu.se.dslab.util.FileUtil;


/**
 * 通过datazone的base_Property、base_Class获取对应的DomainEntity
 * @author sunke
 *
 */
@Service("xmiDomainEntityGetter")
public class XmiDomainEntityGetter {

	private final static String TAG_UML_MODEL = "Model";
	
	//private final static String TAG_UML_PACKAGE = "Package";
	
	private final static String TAG_ATTRIBUTE = "ownedAttribute";
	
	private final static String TAG_PACKAGE = "packagedElement";
	
	private final static String ATTR_XMI_ID = "id";
	
	private final static String ATTR_XMI_TYPE = "type";
	
	private final static String ATTR_XMI_TYPE_PRIMITIVETYPE = "uml:PrimitiveType";
	
	//private final static String ATTR_XMI_TYPE_PROPERTY = "uml:Property";
	
	private final static String ATTR_XMI_TYPE_DATA_TYPE = "uml:DataType";
	
	private final static String ATTR_XMI_TYPE_PACKAGE = "uml:Package";
	
	private final static String ATTR_XMI_TYPE_CLASS = "uml:Class";
	
	private final static String ATTR_TYPE = "type";
	
	/*************************Functional********************************/
	private final static String TAG_DOMAIN_ENTITY = "DomainEntity";
	
	private final static String ATTY_FUNCTIONAL_BASE_CLASS = "base_Class";
	
	private final static String ATTY_FUNCTIONAL_BASE_DATA_TYPE = "base_DataType";
	
	private final static String ATTY_FUNCTIONAL_ENTITY_TYPE = "entity_type";
	
	private final static String ATTY_FUNCTIONAL_ENTITY_URI = "entityURI";
	
	/*************************Functional********************************/
	
	@Resource(name = "dataTypeService")
	private IDataTypeService dataTypeService;
	
	@Resource(name = "domainEntityService")
	private IDomainEntityService domainEntityService;
	
	private Map<String, DomainEntity> resultMap;
	
	private Element rootElm;
	
	public XmiDomainEntityGetter() {
		super();
		resultMap = new HashMap<String, DomainEntity>();
	}

	/**
	 * 根据idset获取对应的domainEntity
	 * @param path--xmi的文件路径（相对地址）
	 * @param idSet--base_property或者base_class的集合
	 * @return key--id；value--DomainEntity
	 */
	public Map<String, DomainEntity> getDomainEntityByPropertyId(String path,Set<String> idSet){
		if (resultMap != null) {
			resultMap = new HashMap<String, DomainEntity>();
		}
		path = FileUtil.getRootPath() + path;
		SAXReader reader = new SAXReader();
		try {
			Document document = reader.read(new File(path));
			rootElm = document.getRootElement();
			getTypeFromAttribute(rootElm,idSet);
		} catch (DocumentException e) {
			e.printStackTrace();
		}
		return resultMap;
	}
	
	@SuppressWarnings("unchecked")
	private void getTypeFromAttribute(Element root,Set<String> idSet){
		//目前分析，所有的对应分析项目均在<uml:Model></uml:Model>类型的node中
		for ( Iterator<Element> first = root.elementIterator(TAG_UML_MODEL); first.hasNext();) {
			Element model = (Element) first.next();
			//System.out.println(model.getName());
			//System.out.println(model.attributeValue(ATTR_XMI_ID));
			for ( Iterator<Element> second = model.elementIterator(TAG_PACKAGE); second.hasNext();) {
				Element packageElement = (Element) second.next();
				recursiveTraversal(packageElement,idSet);
			}
		}
	}
	
	/**
	 * 递归遍历xmi文件查找typeId
	 * @param element--xmi结点
	 * @param id--查找的base_Property
	 * @return typeId
	 */
	@SuppressWarnings("unchecked")
	private void  recursiveTraversal(Element element,Set<String> idSet){
		//System.out.println(element.attributeValue(ATTR_XMI_ID));
		//System.out.println(element.attributeValue(ATTR_XMI_TYPE));
		//基础类型-->直接返回
		if (element.attributeValue(ATTR_XMI_TYPE).equals(ATTR_XMI_TYPE_PRIMITIVETYPE)) {
			return;
		}else if(element.attributeValue(ATTR_XMI_TYPE).equals(ATTR_XMI_TYPE_DATA_TYPE)||
				element.attributeValue(ATTR_XMI_TYPE).equals(ATTR_XMI_TYPE_CLASS)||
				element.attributeValue(ATTR_XMI_TYPE).equals(ATTR_XMI_TYPE_PACKAGE)) {
			for ( Iterator<Element> first = element.elementIterator(TAG_PACKAGE); first.hasNext();) {
				Element model = (Element) first.next();
				recursiveTraversal(model,idSet);
			}
			//目前分析，所有的datazone对应于<ownedAttribute></ownedAttribute>类型的node中
			for ( Iterator<Element> second = element.elementIterator(TAG_ATTRIBUTE); second.hasNext();) {
				Element ownedAttr = (Element) second.next();
				String id = ownedAttr.attributeValue(ATTR_XMI_ID);
				if (idSet.contains(id)) {
					for (Iterator<Attribute> attrIter = ownedAttr.attributeIterator(); attrIter.hasNext(); ) {
						Attribute attribute = (Attribute) attrIter.next();
						//System.out.println("Attribute:"+attribute.getName()+":"+attribute.getValue()+":"+attribute.getNamespacePrefix());
						if (attribute.getName().equals(ATTR_TYPE) && 
								(attribute.getNamespacePrefix() == null||attribute.getNamespacePrefix().equals(""))) {
							//System.out.println("id:"+ownedAttr.attributeValue(ATTR_XMI_ID));
							//System.out.println("type:"+attribute.getValue());
							//System.out.println("name:"+attribute.getName());
							String type = attribute.getValue();
							DomainEntity entity = dataTypeService.getDataTypeByXmiId(type);
							if (entity == null) {
								entity = getDomainEntityFromFunctional(rootElm, type);
							}
							if (entity != null) {
								resultMap.put(id, entity);
								idSet.remove(id);
								break;
							}
						}
					}
				}
			}
		}
	}
	
	/**
	 * 从<Functional:DomainEntity>中获取相对应的uri-->domainEntity
	 * @param root
	 * @param type
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private DomainEntity getDomainEntityFromFunctional(Element root,String type){
		DomainEntity result = null;
		for ( Iterator<Element> first = root.elementIterator(TAG_DOMAIN_ENTITY); first.hasNext();) {
			Element model = (Element) first.next();
			String baseClass = model.attributeValue(ATTY_FUNCTIONAL_BASE_CLASS);
			String baseProperty = model.attributeValue(ATTY_FUNCTIONAL_BASE_DATA_TYPE);
			if ((baseProperty!= null && baseProperty.equals(type))
					||(baseClass!= null && baseClass.equals(type))) {
				String uri = model.attributeValue(ATTY_FUNCTIONAL_ENTITY_URI);
				String entityType = model.attributeValue(ATTY_FUNCTIONAL_ENTITY_TYPE);
				if (entityType.equals("data_entity")) {
					result = domainEntityService.getDomainEntityByUri(uri);
				}else if (entityType.equals("data_type")) {
					result = dataTypeService.getDataTypeByUri(uri);
				}
				return result;
			}
		}
		return result;
	}
//	public static void main(String args[]) {
//		XmiDomainEntityGetter getter = new XmiDomainEntityGetter();
//		Set<String> idSet = new HashSet<String>();
//		idSet.add("GUID+b7a915dd-f1c3-479f-a26b-1c008ad10351");
//		getter.getDomainEntityByPropertyId("E:/DSLab/615/后期/new Rhapsody/Phase4.xmi", idSet);
//	}
}
